home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Snippets / Stuart's Tech Notes / ATP sample code.c < prev    next >
C/C++ Source or Header  |  1994-12-12  |  9KB  |  288 lines

  1. /* (C) 1992 Stuart Cheshire <cheshire@cs.stanford.edu>
  2.  
  3. From: Stuart Cheshire <cheshire@cs.stanford.edu>
  4. Subject: Re: Looking for some sample appletalk ATP code...
  5. Date: Wed, 2 Sep 92 18:11:08 GMT
  6.  
  7. In article <1992Sep1.033635.28604@sunb10.cs.uiuc.edu> Alex Bratton,
  8. bratton@sparc3.cs.uiuc.edu writes:
  9. >If you have some sample code (ATP) that opens, registers, and dumps some
  10. >data, I'd really appreciate seeing it.  This has been bugging me for a while
  11. >and I think I need to look at some working code to see what I'm missing.
  12.  
  13. Here is some sample code, which opens and registers an ATP socket.
  14. It could be used to form the basis of a server which will accept
  15. calls from clients and generate responses. (The code to make the
  16. ATP call from the client is not included -- that is the easy part.)
  17.  
  18. Notes:
  19.  
  20. The code is written for Think C 5.
  21.  
  22. My style of coding is to start with main() at the bottom, and then
  23. work UP the file calling routines defined above. This is basically
  24. because I want full type checking but I'm too lazy to write and
  25. maintain prototypes for every function so I avoid it by defining
  26. every routine before I call it. I hope this doesn't give you headaches.
  27.  
  28. Registering the name "xxxx.xx" (net.node) might seem to invite name
  29. conflicts with other programs, but remember that the type is also
  30. registered: "xxxx.xx:ATP tester@*" so it WILL be unique.
  31. */
  32.  
  33. #include <Traps.h>
  34. #include <GestaltEqu.h>
  35. #include <Folders.h>
  36. #include <AppleTalk.h>
  37.  
  38. #include "StuTypes.h"
  39. #include "StuAppleTalk.h"
  40.  
  41. static unsigned char entity_type[] = "\pATP tester";
  42.  
  43. // Define structures to describe your requests and responses here.
  44. typedef struct { char x; } REQUEST;
  45. typedef struct { char y; } RESPONSE;
  46.  
  47. typedef struct { MPPParamBlock p; long *myglobals; } myMPPParamBlock;
  48. typedef struct { ATPParamBlock p; long *myglobals; } myATPParamBlock;
  49. typedef struct { ATQEntry e;      long *myglobals; } myATQEntry;
  50.  
  51. local OSErr ErrorStatus;        // if non-zero, means that the server is not running
  52. local NamesTableEntry myNTE;    // DONT TOUCH THIS -- IT'S USED CONTINUOUSLY BY NBP
  53. local myATQEntry AppleTalkTransitionQueueEntry;
  54.  
  55. // name must be 8 characters long
  56. local void construct_name(AddrBlock addr, unsigned char *name)
  57.     {
  58.     static unsigned char hextable[] = "0123456789ABCDEF";
  59.     name[0] = 7;
  60.     name[1] = hextable[(addr.aNet  >> 12) & 0xF];
  61.     name[2] = hextable[(addr.aNet  >>  8) & 0xF];
  62.     name[3] = hextable[(addr.aNet  >>  4) & 0xF];
  63.     name[4] = hextable[(addr.aNet  >>  0) & 0xF];
  64.     name[5] = '.';
  65.     name[6] = hextable[(addr.aNode >>  4) & 0xF];
  66.     name[7] = hextable[(addr.aNode >>  0) & 0xF];
  67.     }
  68.  
  69. /**************************************************************************************/
  70.  
  71. // This pair of routines call each other in an infinite ring. When awaitrequest
  72. // gets an incoming request, it calls acceptrequest to dispatch a reply. After
  73. // the reply has been sent, control returns back to awaitrequest.
  74.  
  75. local void awaitrequest(void);
  76. local void acceptrequest(void)
  77.     {
  78.     static RESPONSE resp;
  79.     static BDSElement bds;
  80.     
  81.     myATPParamBlock *atp_pb;
  82.     long *saveGptr;
  83.     asm    {    move.l    GLOBREG, saveGptr
  84.             move.l    a0, atp_pb
  85.             move.l    myATPParamBlock.myglobals(a0), GLOBREG
  86.         }
  87.     
  88.     // if (atp_pb->p.ATPioResult) What to do if error?
  89.  
  90. // Do whatever you want here to prepare your response...
  91. // Note: This is an INTERRUPT TIME completion routine, which means that you
  92. // can't allocate memory, call QuickDraw, put up dialogs to interract with
  93. // the user etc. These things have to be done from your application's main
  94. // event loop, or by using the notification manager.
  95.     
  96.     bds.buffSize  = sizeof(resp);
  97.     bds.buffPtr   = (Ptr)&resp;
  98.     bds.dataSize  = 0;
  99.     bds.userBytes = 0;
  100.     
  101.     atp_pb->p.ATPioCompletion = (ProcPtr)awaitrequest;
  102.     atp_pb->p.ATPatpFlags   = atpEOMvalue;
  103.     atp_pb->p.ATPbdsPointer = (Ptr)&bds;
  104.     atp_pb->p.ATPnumOfBuffs = 1;
  105.     atp_pb->p.ATPbdsSize    = 1;
  106.     
  107.     PSendResponse(&atp_pb->p, TRUE);
  108.  
  109.     asm { move.l saveGptr, GLOBREG }
  110.     }
  111.  
  112. local void awaitrequest(void)
  113.     {
  114.     static REQUEST req;
  115.     myATPParamBlock *atp_pb;
  116.     long *saveGptr;
  117.     asm    {    move.l    GLOBREG, saveGptr
  118.             move.l    a0, atp_pb
  119.             move.l    myATPParamBlock.myglobals(a0), GLOBREG
  120.         }
  121.     atp_pb->p.ATPioCompletion = (ProcPtr)acceptrequest;
  122.     atp_pb->p.ATPatpSocket    = myNTE.nt.nteAddress.aSocket;
  123.     atp_pb->p.ATPreqLength    = sizeof(req);
  124.     atp_pb->p.ATPreqPointer   = (Ptr)&req;
  125.     PGetRequest(&atp_pb->p, TRUE);
  126.     asm { move.l saveGptr, GLOBREG }
  127.     }
  128.  
  129. /**************************************************************************************/
  130.  
  131. // After the name registration below (in AppleTalkStartUp) completes, this routine
  132. // is called to check the return codes, and if all is well it calls awaitrequest();
  133.  
  134. local void register_done(void)
  135.     {
  136.     static myATPParamBlock atp;
  137.     long *saveGptr;
  138.     asm    {    move.l    GLOBREG, saveGptr
  139.             move.l    myMPPParamBlock.myglobals(a0), GLOBREG
  140.             tst.w    ErrorStatus
  141.             bne.s    @e
  142.             move.w    OFFSET(MPPParamBlock,MPPioResult)(a0), ErrorStatus
  143.             bne.s    @e
  144.             clr.w    atp.p.ATPioResult
  145.             move.l    GLOBREG, atp.myglobals
  146.             lea        atp, a0
  147.             bsr        awaitrequest
  148.  
  149.         @e    move.l    saveGptr, GLOBREG
  150.         }
  151.     }
  152.  
  153. /**************************************************************************************/
  154.  
  155. // Startup opens the socket and registers the NBP name on the net.
  156. // ShutDown deregisters the name and closes the socket.
  157.  
  158. // These may be called many times during the lifetime of the program,
  159. // for instance when the PowerBook goes to sleep and then wakes up again,
  160. // when the user unplugs the PowerBook from the network and turns AppleTalk
  161. // off and then later re-connects it and turns AppleTalk back on, when the
  162. // Mac is moved from an Ethernet connection to LocalTalk, or to Token Ring,
  163. // or to ARA dial-up etc.
  164.  
  165. local OSErr AppleTalkStartUp(void)
  166.     {
  167.     if (ErrorStatus == noErr)
  168.         {
  169.         ATPParamBlock atp;
  170.         static myMPPParamBlock p;
  171.         static AddrBlock zeroaddress;
  172.         static unsigned char regname[8];
  173.     
  174.         atp.ATPatpSocket = 0;
  175.         atp.ATPaddrBlock = zeroaddress;
  176.         ErrorStatus = POpenATPSkt(&atp, FALSE);
  177.         if (ErrorStatus) return(ErrorStatus);
  178.     
  179.         p.p.SETSELF.newSelfFlag = TRUE;
  180.         PSetSelfSend(&p.p, FALSE);     // no need to abort if this fails
  181.         
  182.         myNTE.nt.nteAddress.aNet    = ABusVars->sysNetNum;
  183.         myNTE.nt.nteAddress.aNode   = ABusVars->sysLAPAddr;
  184.         myNTE.nt.nteAddress.aSocket = atp.ATPatpSocket;
  185.         
  186.         construct_name(myNTE.nt.nteAddress, regname);
  187.     
  188.         NBPSetNTE((Ptr)&myNTE,
  189.             (Ptr)regname, (Ptr)"\pMacintosh Authenticator", (Ptr)"\p*",
  190.             myNTE.nt.nteAddress.aSocket);
  191.         
  192.         p.p.MPPioCompletion = (ProcPtr)register_done;
  193.         p.p.NBPinterval     = 2;
  194.         p.p.NBPcount        = 8;
  195.         p.p.NBPntQElPtr     = (Ptr)&myNTE;
  196.         p.p.NBPverifyFlag   = TRUE;
  197.         asm { move.l GLOBREG, p.myglobals }
  198.         ErrorStatus = PRegisterName(&p.p, TRUE);
  199.         }
  200.     return(ErrorStatus);
  201.     }
  202.  
  203. local void AppleTalkShutDown(void)
  204.     {
  205.     if (ErrorStatus == noErr)
  206.         {
  207.         ATPParamBlock atpb;
  208.         MPPParamBlock p;
  209.         atpb.ATPatpSocket = myNTE.nt.nteAddress.aSocket;
  210.         PCloseATPSkt(&atpb, FALSE);
  211.         p.NBPentityPtr = myNTE.nt.entityData;
  212.         PRemoveName(&p, FALSE);
  213.         }
  214.     }
  215.  
  216. local long ATalkTransition(long selector, myATQEntry *atq, long param)
  217.     {
  218.     long *saveGptr;
  219.     asm    {    move.l    GLOBREG, saveGptr
  220.             move.l    atq, a0
  221.             move.l    myATQEntry.myglobals(a0), GLOBREG
  222.             cmp.l    #ATTransOpen, selector
  223.             bne.s    @1
  224.             bsr        AppleTalkStartUp
  225.             bra.s    @2
  226.         @1    cmp.l    #ATTransClose, selector
  227.             bne.s    @2
  228.             bsr        AppleTalkShutDown
  229.         @2    move.l    saveGptr, GLOBREG
  230.             clr.l    d0                    ; must return zero
  231.         }
  232.     }
  233.  
  234. /**************************************************************************************/
  235.  
  236. // This assembler is here because the LAPAddATQ and LAPRmvATQ calls provided by
  237. // Apple's nAppleTalk library have a bug which crashes the system when you call them
  238.  
  239. extern pascal OSErr my_LAPAddATQ(ATQEntryPtr theATQEntry);
  240. extern pascal OSErr my_LAPRmvATQ(ATQEntryPtr theATQEntry);
  241. local void assembler(void)
  242.     {
  243.     asm    {
  244.     extern my_LAPAddATQ:
  245.             move.w    #LAddAEQ, d0
  246.             bra.s    @1
  247.     extern my_LAPRmvATQ:
  248.             move.w    #LRmvAEQ, d0
  249.         @1    move.l    4(sp), a0
  250.             move.l    LAPMgrPtr, a1
  251.             move.l    (sp)+, (sp)
  252.             jsr        2(a1)
  253.             move.l    (sp)+, a0
  254.             move.w    d0, (sp)
  255.             jmp        (a0)
  256.         }
  257.     }
  258.  
  259. /**************************************************************************************/
  260.  
  261. // Init is used ONCE, when the program is first loaded, and
  262. // Quit would be called ONCE, finally, if the program exits
  263.  
  264. local OSErr AppleTalkInit(void)    // returns non-zero if init failed
  265.     {
  266.     short MPPRefNum;
  267.     SysEnvRec sysenvirons;
  268.     SysEnvirons(1, &sysenvirons);
  269.     ErrorStatus = OpenDriver("\p.MPP", &MPPRefNum);
  270.     if (ErrorStatus) return(ErrorStatus);
  271.     if (sysenvirons.atDrvrVersNum >= 53)
  272.         {
  273.         AppleTalkTransitionQueueEntry.e.CallAddr = (ProcPtr)ATalkTransition;
  274.         asm { move.l GLOBREG, AppleTalkTransitionQueueEntry.myglobals }
  275.         ErrorStatus = my_LAPAddATQ(&AppleTalkTransitionQueueEntry.e);
  276.         if (ErrorStatus) return(ErrorStatus);
  277.         }
  278.     return(AppleTalkStartUp());
  279.     }
  280.  
  281. local void AppleTalkQuit(void)
  282.     {
  283.     SysEnvRec sysenvirons;
  284.     SysEnvirons(1, &sysenvirons);
  285.     if (sysenvirons.atDrvrVersNum >= 53) my_LAPRmvATQ(&AppleTalkTransitionQueueEntry.e);
  286.     AppleTalkShutDown();
  287.     }
  288.